/* ----------------------------------------------------------------------------
* File: threads.cpp
*
* Desc: Stuffs for POSIX threads
*
* Created: 12/03/2011, by Alexey Korshunov
* ---------------------------------------------------------------------------- */
#include "common.h"
#include "utils.h"


int UtilsThreadCreate(pthread_t *thread, size_t stack_size, void*(*thread_func)(void*), void *arg, FILE *logFile)
{
	int err;
	pthread_attr_t attr;

	err = pthread_attr_init(&attr);
	if (err != 0)
	{
		errno = err;
		if (logFile != NULL)
		{
			fprintf(logFile, "UtilsThreadCreate: Failed to init thread attributes, %s\n", strerror(errno));
			fflush(logFile);
		}
		return UTILS_ERROR;
	}

	if (stack_size != 0)
	{
		err = pthread_attr_setstacksize(&attr, (size_t)stack_size);
		if (err != 0)
		{
			errno = err;
			if (logFile != NULL)
			{
				fprintf(logFile, "UtilsThreadCreate: Failed to set stack size, %s\n", strerror(errno));
				fflush(logFile);
			}
			return UTILS_ERROR;
		}
	}

	err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	if (err != 0)
	{
		errno = err;
		if (logFile != NULL)
		{
			fprintf(logFile, "UtilsThreadCreate: Failed to set detached state, %s\n", strerror(errno));
			fflush(logFile);
		}
		return UTILS_ERROR;
	}
	
	err = pthread_create(thread, &attr, thread_func, arg);
	if (err != 0)
	{
		errno = err;
		if (logFile != NULL)
		{
			fprintf(logFile, "UtilsThreadCreate: Failed to create thread, %s\n", strerror(errno));
			fflush(logFile);
		}
		return UTILS_ERROR;
	}

	err = pthread_attr_destroy(&attr);
	if (err != 0)
	{
		errno = err;
		if (logFile != NULL)
		{
			fprintf(logFile, "UtilsThreadCreate: Failed to destroy thread attributes, %s\n", strerror(errno));
			fflush(logFile);
		}
		return UTILS_ERROR;
	}

	return UTILS_OK;
}


int UtilsThreadCancel(pthread_t *thread, FILE *logFile)
{
	int err;
	err = pthread_cancel(*thread);
	if (err != 0)
	{
		errno = err;
		if (logFile != NULL)
		{
			fprintf(logFile, "UtilsThreadCancel: Failed to cancel thread, %s\n", strerror(errno));
			fflush(logFile);
		}
		return UTILS_ERROR;
	}

	return UTILS_OK;
}


int UtilsThreadKill(pthread_t *thread, int sig, int *status)
{
	int err;
	err = pthread_kill(*thread, sig);
	if (err != 0)
	{
		errno = err;
		*status = err;
		return UTILS_ERROR;
	}
	return UTILS_OK;
}


int UtilsThreadIsExist(pthread_t *thread)
{
	int err;
	err = pthread_kill(*thread, 0);
	if (err == ESRCH)
		return UTILS_ERROR;
	else
		return UTILS_OK;
}